import copy
import math
import os
import sys
import tkinter as tk

import imageio
import matplotlib.pyplot as plt
import numpy as np
import PIL.Image as Image
from matplotlib.backends.backend_agg import FigureCanvasAgg

# current_dir = os.path.dirname(__file__)
# parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir))
# sys.path.append(parent_dir)
from onpolicy.config_env import get_env_config

parser_ev = get_env_config()


def calculate_angle(agent1, agent2):
    # 计算以1为原点，2的角度
    dx = agent2[0] - agent1[0]
    dy = agent2[1] - agent1[1]
    # 使用反三角函数计算角度（以弧度为单位）
    angle_rad = math.atan2(dy, dx)
    # 将弧度转换为角度
    angle_deg = math.degrees(angle_rad)
    # 将角度限制在0到360度之间
    angle_deg = angle_deg % 360
    return angle_deg


class Move_ruler:
    def __init__(self):
        self.init_pos = [0, 0]

    def move(self):
        pass

    def get_init_pos(self):
        return copy.deepcopy(self.init_pos)


class Circle_ruler(Move_ruler):
    def __init__(self, circle_point, radius):
        super().__init__()
        self.circle_point = circle_point.copy()
        self.radius = radius
        self.theta = 0
        self.init_pos = [self.circle_point[0] + self.radius, self.circle_point[1]]

    def move(self):
        # 更新角度
        self.theta += 0.1  # 这里的0.1是角度的增量，你可以根据需要调整
        self.theta %= 2 * math.pi  # 保证角度在[0, 2*pi)范围内
        new_pos = [
            self.circle_point[0] + self.radius * math.cos(self.theta),
            self.circle_point[1] + self.radius * math.sin(self.theta),
        ]
        return new_pos


class Rectangle_ruler(Move_ruler):
    def __init__(self, init_pos, width, height, step=1):
        super().__init__()
        self.width = width
        self.height = height
        self.step = step
        self.len = 0
        self.init_pos = init_pos.copy()
        self.move_list = self.get_rectangle_border(
            init_pos[0], init_pos[1], init_pos[0] + width, init_pos[1] + height, step
        )

    def move(self):
        self.len += 1
        [x, y] = self.move_list[self.len % len(self.move_list)]
        return [x, y]

    def get_rectangle_border(self, x1, y1, x2, y2, step):
        border_points = []
        for x in range(x1, x2, step):
            border_points.append((x, y1))
        for y in range(y1, y2, step):
            border_points.append((x2, y))
        for x in range(x2, x1, -step):
            border_points.append((x, y2))
        for y in range(y2, y1, -step):
            border_points.append((x1, y))
        return border_points


class Draw_ruler(Move_ruler):
    def __init__(self, step=1):
        super().__init__()
        self.step = step
        self.move_list = []
        self.len = 0

    def load_move_list(self, move_list_dir):
        self.move_list = np.load(move_list_dir, allow_pickle=True)
        self.init_pos = self.move_list[0]

    def get_contour(self):
        root = tk.Tk()
        self.canvas = tk.Canvas(root, width=400, height=400)
        self.canvas.pack()
        self.canvas.bind("<Button-1>", self.on_click)
        self.canvas.bind("<B1-Motion>", self.on_drag)
        root.mainloop()
        # 将 move_list 映射到 -20 到 20 之间
        self.move_list = self.map_coordinates(self.move_list, 0, parser_ev["max_map"])
        # 如果 move_list 不为空，且起点和终点不同，将起点添加到列表末尾，形成闭合曲线
        if self.move_list and self.move_list[0] != self.move_list[-1]:
            self.move_list.append(self.move_list[0])
        self.smooth_contour()
        self.init_pos = self.move_list[0]
        return self.move_list

    def on_click(self, event):
        x = event.x
        y = event.y
        self.move_list.append([x, y])

    def on_drag(self, event):
        x = event.x
        y = event.y
        self.move_list.append([x, y])
        self.draw_line()

    def draw_line(self):
        self.canvas.delete("line")
        if len(self.move_list) > 1:
            self.canvas.create_line(self.move_list, tags="line")

    def move(self):
        self.len += 1
        return self.move_list[self.len % len(self.move_list)]

    def is_end(self):
        return self.len > len(self.move_list)

    @staticmethod
    def map_coordinates(coords, min_val, max_val):
        mapped_coords = []
        for x, y in coords:
            # 将 Tkinter 坐标映射到 Matplotlib 坐标
            mapped_x = ((x / 400) * (max_val - min_val)) + min_val
            mapped_y = (((400 - y) / 400) * (max_val - min_val)) + min_val
            mapped_coords.append([mapped_x, mapped_y])
        return mapped_coords

    def smooth_contour(self):
        if len(self.move_list) <= 2:
            return

        smoothed_list = [self.move_list[0]]

        for i in range(1, len(self.move_list)):
            x2, y2 = self.move_list[i]
            while True:
                x1, y1 = smoothed_list[-1]
                distance = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
                if distance <= self.step:
                    smoothed_list.append([x2, y2])
                    break
                else:
                    smoothed_list.append(
                        [
                            x1 + (x2 - x1) / distance * self.step,
                            y1 + (y2 - y1) / distance * self.step,
                        ]
                    )

        self.move_list = smoothed_list


def ruler_main():
    if parser_ev["env_type"] == "Draw" and parser_ev["is_Draw_now"]:
        move_list = Draw_ruler().get_contour()
        np.save("move_list/" + parser_ev["Draw_save_path"], move_list)


def show_move_list():
    result = parser_ev["Draw_file_path"]
    draw_ruler = Draw_ruler()
    draw_ruler.load_move_list(result)
    images = []  # 用于存储每一帧的图像
    while draw_ruler.is_end() == False:
        pos = draw_ruler.move()
        plt.plot(pos[0], pos[1], "ro")
        plt.pause(0.1)
        plt.xlim(-50, 50)
        plt.ylim(-50, 50)
        # 将plt转化为numpy数据
        canvas = FigureCanvasAgg(plt.gcf())
        # # 绘制图像
        canvas.draw()
        # 获取图像尺寸
        w, h = canvas.get_width_height()
        # 解码string 得到argb图像
        buf = np.fromstring(canvas.tostring_argb(), dtype=np.uint8)

        # 重构成w h 4(argb)图像
        buf.shape = (w, h, 4)
        # 转换为 RGBA
        buf = np.roll(buf, 3, axis=2)
        # 得到 Image RGBA图像对象 (需要Image对象的同学到此为止就可以了)
        image = Image.frombytes("RGBA", (w, h), buf.tostring())
        # 转换为numpy array rgba四通道数组
        image = np.asarray(image)
        # 转换为rgb图像
        rgb_image = image[:, :, :3]
        images.append(image)

    imageio.mimsave(parser_ev["Draw_render_path"], images, "GIF", duration=1)
    plt.close()


if __name__ == "__main__":
    ruler_main()
